Loading in Packages

Reading in dataset

nature_data <- read_csv(here("data/training.csv"))
## Rows: 23436 Columns: 2
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (2): text, claim
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Creating Word-Count column - word-count for each claim in the dataset

nature_data <- nature_data %>% 
  mutate(word_count = str_count(nature_data$text, "\\S+"))

Exploring the data

colnames(nature_data)
## [1] "text"       "claim"      "word_count"
unique(nature_data$claim)
##  [1] "5_1" "0_0" "1_1" "2_1" "4_4" "3_3" "4_1" "4_2" "1_7" "3_2" "1_4" "5_2"
## [13] "2_3" "4_5" "1_6" "1_3" "1_2" "3_1"
table(nature_data$claim)
## 
##   0_0   1_1   1_2   1_3   1_4   1_6   1_7   2_1   2_3   3_1   3_2   3_3   4_1 
## 16302   333   147   229   483   189   427   788   339   207   337   323   328 
##   4_2   4_4   4_5   5_1   5_2 
##   190   245   182  1373  1014

Removing all claims with the claim label “0_0”

nature_data_clean <- nature_data %>% filter(!claim == "0_0")

Creating a Horizontal Bar Plot displaying all claim labels and count

ggplot(data = nature_data_clean, aes(x = fct_rev(fct_infreq(claim))))+
  geom_bar(fill = "steelblue", color = "black") +
  theme_minimal() +
  coord_flip() +
  labs(y = "Number of Claims", x = "Type of Claim", title = "Number of Claims by Type")

Organizing the dataset by Super Claim number rather than specific claim labels

nature_data_clean <- nature_data_clean %>% 
  group_by(claim_number = substr(nature_data_clean$claim,1,1)) %>% 
  select(-c("claim"))

Creating a Horizontal Bar Plot displaying all super-claims and count

ggplot(data = nature_data_clean, aes(x = fct_rev(fct_infreq(claim_number))))+
  geom_bar(fill = "steelblue", color = "black") +
  theme_minimal() +
  coord_flip() +
  labs(y = "Number of Claims", x = "Type of Claim", title = "Number of Claims by Type")

Looking at word count distribution by super claim

ggplot(nature_data_clean, aes(x = word_count, fill = claim_number)) +
  geom_histogram(bins = 67, color = "black") +
  theme_minimal()

Analyzing Lexicon Patterns

Tokenize data

nature_data_clean_tokenized <- nature_data_clean[,-2]%>% 
  unnest_tokens(word, text)

Counting tokens

nature_data_clean_tokenized <- nature_data_clean_tokenized %>% 
  count(word) %>% 
  arrange(desc(n))

Filtering tokens for stopwords

nature_data_clean_tokenized <- nature_data_clean_tokenized %>% 
  filter(!word %in% stopwords("english"))

Creating a Wordcloud

wordcloud(words = nature_data_clean_tokenized$word, freq = nature_data_clean_tokenized$n, min.freq = 5, max.words=200, random.order=FALSE, rot.per=0.35,            colors=brewer.pal(8, "RdYlBu"))

Creating a Network Plot

nature_data_clean_corpus <- corpus(nature_data_clean$text)

toks <- nature_data_clean_corpus %>%
    tokens(remove_punct = TRUE) %>%
    tokens_tolower() %>%
    tokens_remove(pattern = stopwords("english"), padding = FALSE)


fcmat <- fcm(toks, context = "window", tri = FALSE)

feat <- names(topfeatures(fcmat, 30))

fcm_select(fcmat, pattern = feat) %>%
    textplot_network(min_freq = 0.5, edge_color = "#E7C100")

Looking at Bigrams

nature_data_clean_claims <- nature_data_clean %>% 
  select(text)
## Adding missing grouping variables: `claim_number`
nature_data_clean_claims 
## # A tibble: 7,134 × 2
## # Groups:   claim_number [5]
##    claim_number text                                                            
##    <chr>        <chr>                                                           
##  1 5            "What do you do if you are a global warming alarmist and real-w…
##  2 1            "Now, I am very interested in the AMO, since it strongly influe…
##  3 2            "There could also be other unknown mechanisms driven by solar c…
##  4 4            "One key problem is the sheer difficulty in building new power …
##  5 1            "I am sure that we can expect to see similar coverage about the…
##  6 3            "According to Donohue and his colleagues, climbing levels of CO…
##  7 1            "Moreover the WBDGE site writes that Arctic sea ice has grown s…
##  8 4            "US energy policy is behind much of the price increase, the Oba…
##  9 5            "First, the computer climate models on which predictions of rap…
## 10 4            "Fourth, experience in Europe shows emissions trading markets a…
## # ℹ 7,124 more rows
ngrams <- nature_data_clean_claims %>% 
  unnest_tokens(bigram, text, token = "ngrams", n = 2)

ngrams <- ngrams %>% 
 separate(bigram, c("word1", "word2"), sep = " ") 

ngrams <- ngrams %>%
  filter(!word1 %in% stop_words$word) %>%
      filter(!word2 %in% stop_words$word)

ngrams <- ngrams %>%
  unite(bigram, word1, word2, sep=" ")

ngrams_counts <- ngrams %>% 
  count(bigram, sort = TRUE)

head(ngrams_counts)
## # A tibble: 6 × 3
## # Groups:   claim_number [2]
##   claim_number bigram             n
##   <chr>        <chr>          <int>
## 1 5            global warming   552
## 2 1            global warming   422
## 3 5            climate change   349
## 4 1            sea level        300
## 5 5            climate models   282
## 6 1            sea ice          246

Looking at Fourgrams

ngrams4 <- nature_data_clean_claims %>% 
  unnest_tokens(fourgram, text, token = "ngrams", n = 4)

ngrams4 <- ngrams4 %>% 
 separate(fourgram, c("word1", "word2", "word3", "word4"), sep = " ") 

ngrams4 <- ngrams4 %>%
  filter(!word1 %in% stop_words$word) %>%
      filter(!word2 %in% stop_words$word) %>% 
        filter(!word3 %in% stop_words$word) %>% 
          filter(!word4 %in% stop_words$word)

ngrams4 <- ngrams4 %>%
  unite(fourgram, word1, word2, word3, word4, sep=" ")

ngrams4_count <- ngrams4 %>% 
  count(fourgram, sort = TRUE)

head(ngrams4_count)
## # A tibble: 6 × 3
## # Groups:   claim_number [3]
##   claim_number fourgram                              n
##   <chr>        <chr>                             <int>
## 1 1            arctic sea ice extent                18
## 2 5            sea surface temperature anomalies    13
## 3 1            antarctic sea ice extent             12
## 4 2            sea surface temperature anomalies    12
## 5 2            sea surface temperature records      12
## 6 1            global warming policy foundation     11

Comparing Lexicon Patterns by Super Claim

Creating Network Plots for each Super Claim

SUPER CLAIM 1 = Global warming is not happening

nature_claim_1 <- nature_data_clean %>% 
  filter(claim_number == "1")

nature_claim_1_corpus <- corpus(nature_claim_1)

toks_claim_1 <- nature_claim_1_corpus %>% 
  tokens(remove_punct = T) %>% 
  tokens_tolower() %>% 
  tokens_remove(pattern = stopwords("english"), padding = F)

fcmat_claim_1 <- fcm(toks_claim_1, context = "window", tri = F)
feat_claim_1 <- names(topfeatures(fcmat_claim_1, 30))

network_claim_1 <- fcm_select(fcmat_claim_1, pattern = feat_claim_1) %>% 
  textplot_network(min_freq = 0.5)

network_claim_1

SUPER CLAIM 2 = Human greenhouse gases are not causing global warming

nature_claim_2 <- nature_data_clean %>% 
  filter(claim_number == "2")

nature_claim_2_corpus <- corpus(nature_claim_2)

toks_claim_2 <- nature_claim_2_corpus %>% 
  tokens(remove_punct = T) %>% 
  tokens_tolower() %>% 
  tokens_remove(pattern = stopwords("english"), padding = F)

fcmat_claim_2 <- fcm(toks_claim_2, context = "window", tri = F)
feat_claim_2 <- names(topfeatures(fcmat_claim_2, 30))

network_claim_2 <- fcm_select(fcmat_claim_2, pattern = feat_claim_2) %>% 
  textplot_network(min_freq = 0.5)

network_claim_2

SUPER CLAIM 3 = Climate impacts are not bad

nature_claim_3 <- nature_data_clean %>% 
  filter(claim_number == "3")

nature_claim_3_corpus <- corpus(nature_claim_3)

toks_claim_3 <- nature_claim_3_corpus %>% 
  tokens(remove_punct = T) %>% 
  tokens_tolower() %>% 
  tokens_remove(pattern = stopwords("english"), padding = F)

fcmat_claim_3 <- fcm(toks_claim_3, context = "window", tri = F)
feat_claim_3 <- names(topfeatures(fcmat_claim_3, 30))

network_claim_3 <- fcm_select(fcmat_claim_3, pattern = feat_claim_3) %>% 
  textplot_network(min_freq = 0.5)
network_claim_3

SUPER CLAIM 4 = Climate solutions won’t work

nature_claim_4 <- nature_data_clean %>% 
  filter(claim_number == "4")

nature_claim_4_corpus <- corpus(nature_claim_4)

toks_claim_4 <- nature_claim_4_corpus %>% 
  tokens(remove_punct = T) %>% 
  tokens_tolower() %>% 
  tokens_remove(pattern = stopwords("english"), padding = F)

fcmat_claim_4 <- fcm(toks_claim_4, context = "window", tri = F)
feat_claim_4 <- names(topfeatures(fcmat_claim_4, 30))

network_claim_4 <- fcm_select(fcmat_claim_4, pattern = feat_claim_4) %>% 
  textplot_network(min_freq = 0.5, edge_color = "#E7C100")
network_claim_4

SUPER CLAIM 5 = Climate movement/science is unreliable

nature_claim_5 <- nature_data_clean %>% 
  filter(claim_number == "5")

nature_claim_5_corpus <- corpus(nature_claim_5)

toks_claim_5 <- nature_claim_5_corpus %>% 
  tokens(remove_punct = T) %>% 
  tokens_tolower() %>% 
  tokens_remove(pattern = stopwords("english"), padding = F)

fcmat_claim_5 <- fcm(toks_claim_5, context = "window", tri = F)
feat_claim_5 <- names(topfeatures(fcmat_claim_5, 30))

network_claim_5 <- fcm_select(fcmat_claim_5, pattern = feat_claim_5) %>% 
  textplot_network(min_freq = 0.5)

network_claim_5

GRID ARRANGE - Putting together all network plots for comparison

grid.arrange(network_claim_1, network_claim_2, network_claim_3, network_claim_4, network_claim_5)
## Warning: ggrepel: 3 unlabeled data points (too many overlaps). Consider increasing max.overlaps
## ggrepel: 3 unlabeled data points (too many overlaps). Consider increasing max.overlaps

Creating a Wordcloud for Super Claim 4

final_wordcloud <- nature_data_clean %>% filter(claim_number == "4") %>% 
  unnest_tokens(word, text) 

final_wordcloud_tokenized <- final_wordcloud %>% 
  count(word) %>% 
  arrange(desc(n))

final_wordcloud_tokenized <- final_wordcloud_tokenized %>% 
  filter(!word %in% stopwords("english"))

wordcloud(words = final_wordcloud_tokenized$word, freq = final_wordcloud_tokenized$n, 
          min.freq = 5, max.words=200, random.order=FALSE, rot.per=0.35,
          colors=brewer.pal(8, "RdYlBu"))

Sentiment Analysis

Reading in dataset - This dataset is a result from running EmoRoBERTa in Google Colab with the nature_data dataset

emoroberta <- read_csv(here("data/climate_change.csv"))
## New names:
## Rows: 7134 Columns: 4
## ── Column specification
## ──────────────────────────────────────────────────────── Delimiter: "," chr
## (3): text, claim, emotion dbl (1): ...1
## ℹ Use `spec()` to retrieve the full column specification for this data. ℹ
## Specify the column types or set `show_col_types = FALSE` to quiet this message.
## • `` -> `...1`

Exploring the dataset

table(emoroberta$emotion)
## 
##     admiration      amusement          anger      annoyance       approval 
##             65             25             10             64            362 
##         caring      confusion      curiosity         desire disappointment 
##              6            161            467             11             53 
##    disapproval        disgust  embarrassment     excitement           fear 
##            346             26             17             34             76 
##      gratitude            joy           love    nervousness        neutral 
##             24             14              2              7           3872 
##       optimism    realization         relief        remorse        sadness 
##             39           1292              1              2             41 
##       surprise 
##            117
unique(emoroberta$emotion)
##  [1] "curiosity"      "approval"       "neutral"        "disapproval"   
##  [5] "realization"    "fear"           "admiration"     "amusement"     
##  [9] "surprise"       "caring"         "gratitude"      "annoyance"     
## [13] "confusion"      "joy"            "sadness"        "excitement"    
## [17] "disappointment" "optimism"       "embarrassment"  "disgust"       
## [21] "desire"         "anger"          "nervousness"    "relief"        
## [25] "remorse"        "love"
dim(emoroberta)
## [1] 7134    4
str(emoroberta)
## spc_tbl_ [7,134 × 4] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ ...1   : num [1:7134] 0 2 6 15 16 17 21 22 23 30 ...
##  $ text   : chr [1:7134] "What do you do if you are a global warming alarmist and real-world temperatures do not warm as much as your cli"| __truncated__ "Now, I am very interested in the AMO, since it strongly influences Atlantic hurricanes, Arctic sea ice, and Gre"| __truncated__ "There could also be other unknown mechanisms driven by solar changes that exaggerate the effect of small variat"| __truncated__ "One key problem is the sheer difficulty in building new power plants in America today. Politically powerful gre"| __truncated__ ...
##  $ claim  : chr [1:7134] "5_1" "1_1" "2_1" "4_4" ...
##  $ emotion: chr [1:7134] "curiosity" "approval" "neutral" "disapproval" ...
##  - attr(*, "spec")=
##   .. cols(
##   ..   ...1 = col_double(),
##   ..   text = col_character(),
##   ..   claim = col_character(),
##   ..   emotion = col_character()
##   .. )
##  - attr(*, "problems")=<externalptr>
colnames(emoroberta)
## [1] "...1"    "text"    "claim"   "emotion"

Cleaning up dataset - Filtering out claims with the “neutral” sentiment, displaying what super-claim belongs to each text

rownames(emoroberta) <-  NULL
emoroberta <- emoroberta[,-1]
emoroberta_clean_1 <- emoroberta %>% 
  group_by(claim_number = substr(emoroberta$claim,1,1)) %>% select(-c("claim")) %>% filter(!emotion == "neutral")

Turning the dataset into a dataframe

emotions <- table(emoroberta_clean_1$emotion)
emotions_data <- data.frame(Emotions = names(emotions), Frequency = as.numeric(emotions))

Creating a horizontal bar plot with sentiment scores

ggplot(emotions_data, aes(x = Frequency, y = reorder(Emotions, Frequency), fill = Emotions)) +
  geom_bar(stat = "identity") +
  theme(legend.position = "none") +
  labs(title = "Sentiment Analysis", x = "Frequency", y = "Emotions")

Creating a dataframe with emotion, claim numbers, and frequency

emotions_data_2 <- table(emoroberta_clean_1$claim_number, emoroberta_clean_1$emotion)
emotions_count <- as.data.frame(emotions_data_2)
names(emotions_count) <- c("Claim_Number", "Emotion", "Frequency")

Creating a bar chart displaying emotions for each super claim and frequency

ggplot(data = emotions_count, aes(x= Frequency, y = Claim_Number)) +
  geom_histogram(aes(fill = Emotion), stat = "identity") +
  coord_flip() +
  labs(x = "Count", y = "Super Claim", title = "Sentiment Analysis")
## Warning in geom_histogram(aes(fill = Emotion), stat = "identity"): Ignoring
## unknown parameters: `binwidth`, `bins`, and `pad`

LS0tCnRpdGxlOiAiQW4gQW5hbHlzaXMgb24gQ2xpbWF0ZSBDaGFuZ2UgTWlzaW5mb3JtYXRpb24gQ2xhaW1zIgphdXRob3I6ICJWaWN0b3JpYSBEZWxhQ3J1eiIKZGF0ZTogIjIwMjMtMDYtMjgiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDoKICAgIGNvZGVfZG93bmxvYWQ6IFRSVUUKLS0tCgpMb2FkaW5nIGluIFBhY2thZ2VzCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCmxpYnJhcnkoanNvbmxpdGUpICMgYWxsb3dzIHVzIHRvIHJlYWQgaW4ganNvbiBmaWxlcwpsaWJyYXJ5KHRpZHl2ZXJzZSkgIyBhbGxvd3MgdXMgdG8gZG8gbG90cyBvZiBkYXRhIG1hbmlwdWxhdGlvbiBhbmQgYmFzaWMgZGF0YSBzY2llbmNlCmxpYnJhcnkoaGVyZSkgIyBhbGxvd3MgdXMgdG8gY3V0IG91dCBsb25nIGZpbGUgcGF0aHMgKGV4LiAidXNlcnMvY29ubm9yL2Rvd2xvYWRzL2V0YyIpCmxpYnJhcnkoZm9yY2F0cykgIyAKbGlicmFyeSh0aWR5dGV4dCkgIyBhbGxvd3MgdXMgdG8gdG9rZW5pemUgZGF0YSAKbGlicmFyeShkcGx5cikgIyBhbGxvd3MgdXMgdG8gbWFuaXB1bGF0ZSBkYXRhZnJhbWVzCmxpYnJhcnkoc3RyaW5ncikgIyBhbGxvd3MgdXMgdG8gY291bnQgdGhlIG51bWJlciBvZiB3b3JkcyBpbiBhIGNlbGwKbGlicmFyeShxdWFudGVkYSkgIyBhbGxvd3MgdXMgdG8gdG9rZW5pemUgZGF0YQpsaWJyYXJ5KHF1YW50ZWRhLnRleHRwbG90cykgIyBhbGxvd3MgdXMgdG8gbWFrZSBuZXR3b3JrIHBsb3RzCmxpYnJhcnkoZ3JpZEV4dHJhKSAjIGFsbG93cyB1cyB0byBjb21iaW5lIG11bHRpcGxlIHBsb3RzIGludG8gMQpsaWJyYXJ5KHdvcmRjbG91ZCkgIyBhbGxvd3MgdXMgdG8gZ2VuZXJhdGUgd29yZCBjbG91ZHMKbGlicmFyeShxZGFwRGljdGlvbmFyaWVzKQpgYGAKClJlYWRpbmcgaW4gZGF0YXNldApgYGB7cn0KbmF0dXJlX2RhdGEgPC0gcmVhZF9jc3YoaGVyZSgiZGF0YS90cmFpbmluZy5jc3YiKSkKYGBgCkNyZWF0aW5nIFdvcmQtQ291bnQgY29sdW1uCi0gd29yZC1jb3VudCBmb3IgZWFjaCBjbGFpbSBpbiB0aGUgZGF0YXNldApgYGB7cn0KbmF0dXJlX2RhdGEgPC0gbmF0dXJlX2RhdGEgJT4lIAogIG11dGF0ZSh3b3JkX2NvdW50ID0gc3RyX2NvdW50KG5hdHVyZV9kYXRhJHRleHQsICJcXFMrIikpCmBgYAoKIyMgRXhwbG9yaW5nIHRoZSBkYXRhCmBgYHtyfQpjb2xuYW1lcyhuYXR1cmVfZGF0YSkKdW5pcXVlKG5hdHVyZV9kYXRhJGNsYWltKQp0YWJsZShuYXR1cmVfZGF0YSRjbGFpbSkKYGBgClJlbW92aW5nIGFsbCBjbGFpbXMgd2l0aCB0aGUgY2xhaW0gbGFiZWwgIjBfMCIKYGBge3J9Cm5hdHVyZV9kYXRhX2NsZWFuIDwtIG5hdHVyZV9kYXRhICU+JSBmaWx0ZXIoIWNsYWltID09ICIwXzAiKQpgYGAKCkNyZWF0aW5nIGEgSG9yaXpvbnRhbCBCYXIgUGxvdCBkaXNwbGF5aW5nIGFsbCBjbGFpbSBsYWJlbHMgYW5kIGNvdW50CmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IG5hdHVyZV9kYXRhX2NsZWFuLCBhZXMoeCA9IGZjdF9yZXYoZmN0X2luZnJlcShjbGFpbSkpKSkrCiAgZ2VvbV9iYXIoZmlsbCA9ICJzdGVlbGJsdWUiLCBjb2xvciA9ICJibGFjayIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGNvb3JkX2ZsaXAoKSArCiAgbGFicyh5ID0gIk51bWJlciBvZiBDbGFpbXMiLCB4ID0gIlR5cGUgb2YgQ2xhaW0iLCB0aXRsZSA9ICJOdW1iZXIgb2YgQ2xhaW1zIGJ5IFR5cGUiKQpgYGAKT3JnYW5pemluZyB0aGUgZGF0YXNldCBieSBTdXBlciBDbGFpbSBudW1iZXIgcmF0aGVyIHRoYW4gc3BlY2lmaWMgY2xhaW0gbGFiZWxzCmBgYHtyfQpuYXR1cmVfZGF0YV9jbGVhbiA8LSBuYXR1cmVfZGF0YV9jbGVhbiAlPiUgCiAgZ3JvdXBfYnkoY2xhaW1fbnVtYmVyID0gc3Vic3RyKG5hdHVyZV9kYXRhX2NsZWFuJGNsYWltLDEsMSkpICU+JSAKICBzZWxlY3QoLWMoImNsYWltIikpCmBgYAoKQ3JlYXRpbmcgYSBIb3Jpem9udGFsIEJhciBQbG90IGRpc3BsYXlpbmcgYWxsIHN1cGVyLWNsYWltcyBhbmQgY291bnQKYGBge3J9CmdncGxvdChkYXRhID0gbmF0dXJlX2RhdGFfY2xlYW4sIGFlcyh4ID0gZmN0X3JldihmY3RfaW5mcmVxKGNsYWltX251bWJlcikpKSkrCiAgZ2VvbV9iYXIoZmlsbCA9ICJzdGVlbGJsdWUiLCBjb2xvciA9ICJibGFjayIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGNvb3JkX2ZsaXAoKSArCiAgbGFicyh5ID0gIk51bWJlciBvZiBDbGFpbXMiLCB4ID0gIlR5cGUgb2YgQ2xhaW0iLCB0aXRsZSA9ICJOdW1iZXIgb2YgQ2xhaW1zIGJ5IFR5cGUiKQpgYGAKTG9va2luZyBhdCB3b3JkIGNvdW50IGRpc3RyaWJ1dGlvbiBieSBzdXBlciBjbGFpbQpgYGB7cn0KZ2dwbG90KG5hdHVyZV9kYXRhX2NsZWFuLCBhZXMoeCA9IHdvcmRfY291bnQsIGZpbGwgPSBjbGFpbV9udW1iZXIpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDY3LCBjb2xvciA9ICJibGFjayIpICsKICB0aGVtZV9taW5pbWFsKCkKYGBgCgojIyBBbmFseXppbmcgTGV4aWNvbiBQYXR0ZXJucyAKClRva2VuaXplIGRhdGEKYGBge3J9Cm5hdHVyZV9kYXRhX2NsZWFuX3Rva2VuaXplZCA8LSBuYXR1cmVfZGF0YV9jbGVhblssLTJdJT4lIAogIHVubmVzdF90b2tlbnMod29yZCwgdGV4dCkKYGBgCgpDb3VudGluZyB0b2tlbnMKYGBge3J9Cm5hdHVyZV9kYXRhX2NsZWFuX3Rva2VuaXplZCA8LSBuYXR1cmVfZGF0YV9jbGVhbl90b2tlbml6ZWQgJT4lIAogIGNvdW50KHdvcmQpICU+JSAKICBhcnJhbmdlKGRlc2MobikpCmBgYAoKRmlsdGVyaW5nIHRva2VucyBmb3Igc3RvcHdvcmRzCmBgYHtyfQpuYXR1cmVfZGF0YV9jbGVhbl90b2tlbml6ZWQgPC0gbmF0dXJlX2RhdGFfY2xlYW5fdG9rZW5pemVkICU+JSAKICBmaWx0ZXIoIXdvcmQgJWluJSBzdG9wd29yZHMoImVuZ2xpc2giKSkKYGBgCgpDcmVhdGluZyBhIFdvcmRjbG91ZApgYGB7cn0Kd29yZGNsb3VkKHdvcmRzID0gbmF0dXJlX2RhdGFfY2xlYW5fdG9rZW5pemVkJHdvcmQsIGZyZXEgPSBuYXR1cmVfZGF0YV9jbGVhbl90b2tlbml6ZWQkbiwgbWluLmZyZXEgPSA1LCBtYXgud29yZHM9MjAwLCByYW5kb20ub3JkZXI9RkFMU0UsIHJvdC5wZXI9MC4zNSwgICAgICAgICAgICBjb2xvcnM9YnJld2VyLnBhbCg4LCAiUmRZbEJ1IikpCmBgYAoKQ3JlYXRpbmcgYSBOZXR3b3JrIFBsb3QKYGBge3J9Cm5hdHVyZV9kYXRhX2NsZWFuX2NvcnB1cyA8LSBjb3JwdXMobmF0dXJlX2RhdGFfY2xlYW4kdGV4dCkKCnRva3MgPC0gbmF0dXJlX2RhdGFfY2xlYW5fY29ycHVzICU+JQogICAgdG9rZW5zKHJlbW92ZV9wdW5jdCA9IFRSVUUpICU+JQogICAgdG9rZW5zX3RvbG93ZXIoKSAlPiUKICAgIHRva2Vuc19yZW1vdmUocGF0dGVybiA9IHN0b3B3b3JkcygiZW5nbGlzaCIpLCBwYWRkaW5nID0gRkFMU0UpCgoKZmNtYXQgPC0gZmNtKHRva3MsIGNvbnRleHQgPSAid2luZG93IiwgdHJpID0gRkFMU0UpCgpmZWF0IDwtIG5hbWVzKHRvcGZlYXR1cmVzKGZjbWF0LCAzMCkpCgpmY21fc2VsZWN0KGZjbWF0LCBwYXR0ZXJuID0gZmVhdCkgJT4lCiAgICB0ZXh0cGxvdF9uZXR3b3JrKG1pbl9mcmVxID0gMC41LCBlZGdlX2NvbG9yID0gIiNFN0MxMDAiKQpgYGAKCkxvb2tpbmcgYXQgQmlncmFtcyAKYGBge3J9Cm5hdHVyZV9kYXRhX2NsZWFuX2NsYWltcyA8LSBuYXR1cmVfZGF0YV9jbGVhbiAlPiUgCiAgc2VsZWN0KHRleHQpCm5hdHVyZV9kYXRhX2NsZWFuX2NsYWltcyAKCm5ncmFtcyA8LSBuYXR1cmVfZGF0YV9jbGVhbl9jbGFpbXMgJT4lIAogIHVubmVzdF90b2tlbnMoYmlncmFtLCB0ZXh0LCB0b2tlbiA9ICJuZ3JhbXMiLCBuID0gMikKCm5ncmFtcyA8LSBuZ3JhbXMgJT4lIAogc2VwYXJhdGUoYmlncmFtLCBjKCJ3b3JkMSIsICJ3b3JkMiIpLCBzZXAgPSAiICIpIAoKbmdyYW1zIDwtIG5ncmFtcyAlPiUKICBmaWx0ZXIoIXdvcmQxICVpbiUgc3RvcF93b3JkcyR3b3JkKSAlPiUKICAgICAgZmlsdGVyKCF3b3JkMiAlaW4lIHN0b3Bfd29yZHMkd29yZCkKCm5ncmFtcyA8LSBuZ3JhbXMgJT4lCiAgdW5pdGUoYmlncmFtLCB3b3JkMSwgd29yZDIsIHNlcD0iICIpCgpuZ3JhbXNfY291bnRzIDwtIG5ncmFtcyAlPiUgCiAgY291bnQoYmlncmFtLCBzb3J0ID0gVFJVRSkKCmhlYWQobmdyYW1zX2NvdW50cykKYGBgCkxvb2tpbmcgYXQgRm91cmdyYW1zCmBgYHtyfQpuZ3JhbXM0IDwtIG5hdHVyZV9kYXRhX2NsZWFuX2NsYWltcyAlPiUgCiAgdW5uZXN0X3Rva2Vucyhmb3VyZ3JhbSwgdGV4dCwgdG9rZW4gPSAibmdyYW1zIiwgbiA9IDQpCgpuZ3JhbXM0IDwtIG5ncmFtczQgJT4lIAogc2VwYXJhdGUoZm91cmdyYW0sIGMoIndvcmQxIiwgIndvcmQyIiwgIndvcmQzIiwgIndvcmQ0IiksIHNlcCA9ICIgIikgCgpuZ3JhbXM0IDwtIG5ncmFtczQgJT4lCiAgZmlsdGVyKCF3b3JkMSAlaW4lIHN0b3Bfd29yZHMkd29yZCkgJT4lCiAgICAgIGZpbHRlcighd29yZDIgJWluJSBzdG9wX3dvcmRzJHdvcmQpICU+JSAKICAgICAgICBmaWx0ZXIoIXdvcmQzICVpbiUgc3RvcF93b3JkcyR3b3JkKSAlPiUgCiAgICAgICAgICBmaWx0ZXIoIXdvcmQ0ICVpbiUgc3RvcF93b3JkcyR3b3JkKQoKbmdyYW1zNCA8LSBuZ3JhbXM0ICU+JQogIHVuaXRlKGZvdXJncmFtLCB3b3JkMSwgd29yZDIsIHdvcmQzLCB3b3JkNCwgc2VwPSIgIikKCm5ncmFtczRfY291bnQgPC0gbmdyYW1zNCAlPiUgCiAgY291bnQoZm91cmdyYW0sIHNvcnQgPSBUUlVFKQoKaGVhZChuZ3JhbXM0X2NvdW50KQpgYGAKCiMjIENvbXBhcmluZyBMZXhpY29uIFBhdHRlcm5zIGJ5IFN1cGVyIENsYWltIApDcmVhdGluZyBOZXR3b3JrIFBsb3RzIGZvciBlYWNoIFN1cGVyIENsYWltCgpTVVBFUiBDTEFJTSAxID0gR2xvYmFsIHdhcm1pbmcgaXMgbm90IGhhcHBlbmluZwpgYGB7cn0KbmF0dXJlX2NsYWltXzEgPC0gbmF0dXJlX2RhdGFfY2xlYW4gJT4lIAogIGZpbHRlcihjbGFpbV9udW1iZXIgPT0gIjEiKQoKbmF0dXJlX2NsYWltXzFfY29ycHVzIDwtIGNvcnB1cyhuYXR1cmVfY2xhaW1fMSkKCnRva3NfY2xhaW1fMSA8LSBuYXR1cmVfY2xhaW1fMV9jb3JwdXMgJT4lIAogIHRva2VucyhyZW1vdmVfcHVuY3QgPSBUKSAlPiUgCiAgdG9rZW5zX3RvbG93ZXIoKSAlPiUgCiAgdG9rZW5zX3JlbW92ZShwYXR0ZXJuID0gc3RvcHdvcmRzKCJlbmdsaXNoIiksIHBhZGRpbmcgPSBGKQoKZmNtYXRfY2xhaW1fMSA8LSBmY20odG9rc19jbGFpbV8xLCBjb250ZXh0ID0gIndpbmRvdyIsIHRyaSA9IEYpCmZlYXRfY2xhaW1fMSA8LSBuYW1lcyh0b3BmZWF0dXJlcyhmY21hdF9jbGFpbV8xLCAzMCkpCgpuZXR3b3JrX2NsYWltXzEgPC0gZmNtX3NlbGVjdChmY21hdF9jbGFpbV8xLCBwYXR0ZXJuID0gZmVhdF9jbGFpbV8xKSAlPiUgCiAgdGV4dHBsb3RfbmV0d29yayhtaW5fZnJlcSA9IDAuNSkKCm5ldHdvcmtfY2xhaW1fMQpgYGAKClNVUEVSIENMQUlNIDIgPSBIdW1hbiBncmVlbmhvdXNlIGdhc2VzIGFyZSBub3QgY2F1c2luZyBnbG9iYWwgd2FybWluZwpgYGB7cn0KbmF0dXJlX2NsYWltXzIgPC0gbmF0dXJlX2RhdGFfY2xlYW4gJT4lIAogIGZpbHRlcihjbGFpbV9udW1iZXIgPT0gIjIiKQoKbmF0dXJlX2NsYWltXzJfY29ycHVzIDwtIGNvcnB1cyhuYXR1cmVfY2xhaW1fMikKCnRva3NfY2xhaW1fMiA8LSBuYXR1cmVfY2xhaW1fMl9jb3JwdXMgJT4lIAogIHRva2VucyhyZW1vdmVfcHVuY3QgPSBUKSAlPiUgCiAgdG9rZW5zX3RvbG93ZXIoKSAlPiUgCiAgdG9rZW5zX3JlbW92ZShwYXR0ZXJuID0gc3RvcHdvcmRzKCJlbmdsaXNoIiksIHBhZGRpbmcgPSBGKQoKZmNtYXRfY2xhaW1fMiA8LSBmY20odG9rc19jbGFpbV8yLCBjb250ZXh0ID0gIndpbmRvdyIsIHRyaSA9IEYpCmZlYXRfY2xhaW1fMiA8LSBuYW1lcyh0b3BmZWF0dXJlcyhmY21hdF9jbGFpbV8yLCAzMCkpCgpuZXR3b3JrX2NsYWltXzIgPC0gZmNtX3NlbGVjdChmY21hdF9jbGFpbV8yLCBwYXR0ZXJuID0gZmVhdF9jbGFpbV8yKSAlPiUgCiAgdGV4dHBsb3RfbmV0d29yayhtaW5fZnJlcSA9IDAuNSkKCm5ldHdvcmtfY2xhaW1fMgpgYGAKClNVUEVSIENMQUlNIDMgPSBDbGltYXRlIGltcGFjdHMgYXJlIG5vdCBiYWQKYGBge3J9Cm5hdHVyZV9jbGFpbV8zIDwtIG5hdHVyZV9kYXRhX2NsZWFuICU+JSAKICBmaWx0ZXIoY2xhaW1fbnVtYmVyID09ICIzIikKCm5hdHVyZV9jbGFpbV8zX2NvcnB1cyA8LSBjb3JwdXMobmF0dXJlX2NsYWltXzMpCgp0b2tzX2NsYWltXzMgPC0gbmF0dXJlX2NsYWltXzNfY29ycHVzICU+JSAKICB0b2tlbnMocmVtb3ZlX3B1bmN0ID0gVCkgJT4lIAogIHRva2Vuc190b2xvd2VyKCkgJT4lIAogIHRva2Vuc19yZW1vdmUocGF0dGVybiA9IHN0b3B3b3JkcygiZW5nbGlzaCIpLCBwYWRkaW5nID0gRikKCmZjbWF0X2NsYWltXzMgPC0gZmNtKHRva3NfY2xhaW1fMywgY29udGV4dCA9ICJ3aW5kb3ciLCB0cmkgPSBGKQpmZWF0X2NsYWltXzMgPC0gbmFtZXModG9wZmVhdHVyZXMoZmNtYXRfY2xhaW1fMywgMzApKQoKbmV0d29ya19jbGFpbV8zIDwtIGZjbV9zZWxlY3QoZmNtYXRfY2xhaW1fMywgcGF0dGVybiA9IGZlYXRfY2xhaW1fMykgJT4lIAogIHRleHRwbG90X25ldHdvcmsobWluX2ZyZXEgPSAwLjUpCm5ldHdvcmtfY2xhaW1fMwpgYGAKClNVUEVSIENMQUlNIDQgPSBDbGltYXRlIHNvbHV0aW9ucyB3b24ndCB3b3JrCmBgYHtyfQpuYXR1cmVfY2xhaW1fNCA8LSBuYXR1cmVfZGF0YV9jbGVhbiAlPiUgCiAgZmlsdGVyKGNsYWltX251bWJlciA9PSAiNCIpCgpuYXR1cmVfY2xhaW1fNF9jb3JwdXMgPC0gY29ycHVzKG5hdHVyZV9jbGFpbV80KQoKdG9rc19jbGFpbV80IDwtIG5hdHVyZV9jbGFpbV80X2NvcnB1cyAlPiUgCiAgdG9rZW5zKHJlbW92ZV9wdW5jdCA9IFQpICU+JSAKICB0b2tlbnNfdG9sb3dlcigpICU+JSAKICB0b2tlbnNfcmVtb3ZlKHBhdHRlcm4gPSBzdG9wd29yZHMoImVuZ2xpc2giKSwgcGFkZGluZyA9IEYpCgpmY21hdF9jbGFpbV80IDwtIGZjbSh0b2tzX2NsYWltXzQsIGNvbnRleHQgPSAid2luZG93IiwgdHJpID0gRikKZmVhdF9jbGFpbV80IDwtIG5hbWVzKHRvcGZlYXR1cmVzKGZjbWF0X2NsYWltXzQsIDMwKSkKCm5ldHdvcmtfY2xhaW1fNCA8LSBmY21fc2VsZWN0KGZjbWF0X2NsYWltXzQsIHBhdHRlcm4gPSBmZWF0X2NsYWltXzQpICU+JSAKICB0ZXh0cGxvdF9uZXR3b3JrKG1pbl9mcmVxID0gMC41LCBlZGdlX2NvbG9yID0gIiNFN0MxMDAiKQpuZXR3b3JrX2NsYWltXzQKYGBgClNVUEVSIENMQUlNIDUgPSBDbGltYXRlIG1vdmVtZW50L3NjaWVuY2UgaXMgdW5yZWxpYWJsZQpgYGB7cn0KbmF0dXJlX2NsYWltXzUgPC0gbmF0dXJlX2RhdGFfY2xlYW4gJT4lIAogIGZpbHRlcihjbGFpbV9udW1iZXIgPT0gIjUiKQoKbmF0dXJlX2NsYWltXzVfY29ycHVzIDwtIGNvcnB1cyhuYXR1cmVfY2xhaW1fNSkKCnRva3NfY2xhaW1fNSA8LSBuYXR1cmVfY2xhaW1fNV9jb3JwdXMgJT4lIAogIHRva2VucyhyZW1vdmVfcHVuY3QgPSBUKSAlPiUgCiAgdG9rZW5zX3RvbG93ZXIoKSAlPiUgCiAgdG9rZW5zX3JlbW92ZShwYXR0ZXJuID0gc3RvcHdvcmRzKCJlbmdsaXNoIiksIHBhZGRpbmcgPSBGKQoKZmNtYXRfY2xhaW1fNSA8LSBmY20odG9rc19jbGFpbV81LCBjb250ZXh0ID0gIndpbmRvdyIsIHRyaSA9IEYpCmZlYXRfY2xhaW1fNSA8LSBuYW1lcyh0b3BmZWF0dXJlcyhmY21hdF9jbGFpbV81LCAzMCkpCgpuZXR3b3JrX2NsYWltXzUgPC0gZmNtX3NlbGVjdChmY21hdF9jbGFpbV81LCBwYXR0ZXJuID0gZmVhdF9jbGFpbV81KSAlPiUgCiAgdGV4dHBsb3RfbmV0d29yayhtaW5fZnJlcSA9IDAuNSkKCm5ldHdvcmtfY2xhaW1fNQoKYGBgCgpHUklEIEFSUkFOR0UKLSBQdXR0aW5nIHRvZ2V0aGVyIGFsbCBuZXR3b3JrIHBsb3RzIGZvciBjb21wYXJpc29uCmBgYHtyfQpncmlkLmFycmFuZ2UobmV0d29ya19jbGFpbV8xLCBuZXR3b3JrX2NsYWltXzIsIG5ldHdvcmtfY2xhaW1fMywgbmV0d29ya19jbGFpbV80LCBuZXR3b3JrX2NsYWltXzUpCmBgYAoKQ3JlYXRpbmcgYSBXb3JkY2xvdWQgZm9yIFN1cGVyIENsYWltIDQKYGBge3J9CmZpbmFsX3dvcmRjbG91ZCA8LSBuYXR1cmVfZGF0YV9jbGVhbiAlPiUgZmlsdGVyKGNsYWltX251bWJlciA9PSAiNCIpICU+JSAKICB1bm5lc3RfdG9rZW5zKHdvcmQsIHRleHQpIAoKZmluYWxfd29yZGNsb3VkX3Rva2VuaXplZCA8LSBmaW5hbF93b3JkY2xvdWQgJT4lIAogIGNvdW50KHdvcmQpICU+JSAKICBhcnJhbmdlKGRlc2MobikpCgpmaW5hbF93b3JkY2xvdWRfdG9rZW5pemVkIDwtIGZpbmFsX3dvcmRjbG91ZF90b2tlbml6ZWQgJT4lIAogIGZpbHRlcighd29yZCAlaW4lIHN0b3B3b3JkcygiZW5nbGlzaCIpKQoKd29yZGNsb3VkKHdvcmRzID0gZmluYWxfd29yZGNsb3VkX3Rva2VuaXplZCR3b3JkLCBmcmVxID0gZmluYWxfd29yZGNsb3VkX3Rva2VuaXplZCRuLCAKICAgICAgICAgIG1pbi5mcmVxID0gNSwgbWF4LndvcmRzPTIwMCwgcmFuZG9tLm9yZGVyPUZBTFNFLCByb3QucGVyPTAuMzUsCiAgICAgICAgICBjb2xvcnM9YnJld2VyLnBhbCg4LCAiUmRZbEJ1IikpCmBgYAoKCiMjIFNlbnRpbWVudCBBbmFseXNpcwpSZWFkaW5nIGluIGRhdGFzZXQKLSBUaGlzIGRhdGFzZXQgaXMgYSByZXN1bHQgZnJvbSBydW5uaW5nIEVtb1JvQkVSVGEgaW4gR29vZ2xlIENvbGFiIHdpdGggdGhlIG5hdHVyZV9kYXRhIGRhdGFzZXQKYGBge3J9CmVtb3JvYmVydGEgPC0gcmVhZF9jc3YoaGVyZSgiZGF0YS9jbGltYXRlX2NoYW5nZS5jc3YiKSkKYGBgCgpFeHBsb3JpbmcgdGhlIGRhdGFzZXQKYGBge3J9CnRhYmxlKGVtb3JvYmVydGEkZW1vdGlvbikKdW5pcXVlKGVtb3JvYmVydGEkZW1vdGlvbikKYGBgCgpgYGB7cn0KZGltKGVtb3JvYmVydGEpCnN0cihlbW9yb2JlcnRhKQpjb2xuYW1lcyhlbW9yb2JlcnRhKQpgYGAKQ2xlYW5pbmcgdXAgZGF0YXNldAotIEZpbHRlcmluZyBvdXQgY2xhaW1zIHdpdGggdGhlICJuZXV0cmFsIiBzZW50aW1lbnQsIGRpc3BsYXlpbmcgd2hhdCBzdXBlci1jbGFpbSBiZWxvbmdzIHRvIGVhY2ggdGV4dApgYGB7cn0Kcm93bmFtZXMoZW1vcm9iZXJ0YSkgPC0gIE5VTEwKZW1vcm9iZXJ0YSA8LSBlbW9yb2JlcnRhWywtMV0KZW1vcm9iZXJ0YV9jbGVhbl8xIDwtIGVtb3JvYmVydGEgJT4lIAogIGdyb3VwX2J5KGNsYWltX251bWJlciA9IHN1YnN0cihlbW9yb2JlcnRhJGNsYWltLDEsMSkpICU+JSBzZWxlY3QoLWMoImNsYWltIikpICU+JSBmaWx0ZXIoIWVtb3Rpb24gPT0gIm5ldXRyYWwiKQpgYGAKClR1cm5pbmcgdGhlIGRhdGFzZXQgaW50byBhIGRhdGFmcmFtZQpgYGB7cn0KZW1vdGlvbnMgPC0gdGFibGUoZW1vcm9iZXJ0YV9jbGVhbl8xJGVtb3Rpb24pCmVtb3Rpb25zX2RhdGEgPC0gZGF0YS5mcmFtZShFbW90aW9ucyA9IG5hbWVzKGVtb3Rpb25zKSwgRnJlcXVlbmN5ID0gYXMubnVtZXJpYyhlbW90aW9ucykpCmBgYAoKQ3JlYXRpbmcgYSBob3Jpem9udGFsIGJhciBwbG90IHdpdGggc2VudGltZW50IHNjb3JlcwpgYGB7cn0KZ2dwbG90KGVtb3Rpb25zX2RhdGEsIGFlcyh4ID0gRnJlcXVlbmN5LCB5ID0gcmVvcmRlcihFbW90aW9ucywgRnJlcXVlbmN5KSwgZmlsbCA9IEVtb3Rpb25zKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgbGFicyh0aXRsZSA9ICJTZW50aW1lbnQgQW5hbHlzaXMiLCB4ID0gIkZyZXF1ZW5jeSIsIHkgPSAiRW1vdGlvbnMiKQpgYGAKCkNyZWF0aW5nIGEgZGF0YWZyYW1lIHdpdGggZW1vdGlvbiwgY2xhaW0gbnVtYmVycywgYW5kIGZyZXF1ZW5jeQpgYGB7cn0KZW1vdGlvbnNfZGF0YV8yIDwtIHRhYmxlKGVtb3JvYmVydGFfY2xlYW5fMSRjbGFpbV9udW1iZXIsIGVtb3JvYmVydGFfY2xlYW5fMSRlbW90aW9uKQplbW90aW9uc19jb3VudCA8LSBhcy5kYXRhLmZyYW1lKGVtb3Rpb25zX2RhdGFfMikKbmFtZXMoZW1vdGlvbnNfY291bnQpIDwtIGMoIkNsYWltX051bWJlciIsICJFbW90aW9uIiwgIkZyZXF1ZW5jeSIpCmBgYAoKQ3JlYXRpbmcgYSBiYXIgY2hhcnQgZGlzcGxheWluZyBlbW90aW9ucyBmb3IgZWFjaCBzdXBlciBjbGFpbSBhbmQgZnJlcXVlbmN5CmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGVtb3Rpb25zX2NvdW50LCBhZXMoeD0gRnJlcXVlbmN5LCB5ID0gQ2xhaW1fTnVtYmVyKSkgKwogIGdlb21faGlzdG9ncmFtKGFlcyhmaWxsID0gRW1vdGlvbiksIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgY29vcmRfZmxpcCgpICsKICBsYWJzKHggPSAiQ291bnQiLCB5ID0gIlN1cGVyIENsYWltIiwgdGl0bGUgPSAiU2VudGltZW50IEFuYWx5c2lzIikKYGBgCg==